﻿using System;
using System.Collections.Generic;
using BattleCity.Classes;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace BattleCity.GameObjects
{
    public enum Direction
    {
        Up,
        Down,
        Left,
        Right
    }
    public class Me : Tank
    {
        //Анимация режима бессмертия
        Animation _godModeUp;
        Animation _godModeDown;
        Animation _godModeLeft;
        Animation _godModeRight;

        //Набор переменных-флагов
        bool _isMoveNow, _flag, _stoneBase, _freezedEnemies, _isDie;
        public bool _isGod;
        int _iter;
        double _stoneBaseTime, _freezeTime, _godModeTime;
        //Данные игрока
        public int Score { get; set; }
        public byte Skill { get; set; }

        //Список стен базы
        List<Wall> _baseWalls;
        List<Stone> _stoneBaseWalls;

        //Звуки игрока
        SoundEffect _moveSound;
        SoundEffect _engineSound;
        SoundEffect _bonusSound;
        SoundEffect _lifeSound;
        SoundEffect _skillSound;

        public event EventHandler GameOver;

        public Me(BattleCityGame game, ref AnimationPlayer _spr, Vector2 _sprPosition,
            ref Dictionary<string, Animation> _animList, ref Dictionary<string, SoundEffect> _soundList)
            : base(game, ref _spr, _sprPosition)
        {
            _dir = Direction.Up;
            IsAlive = true;
            Lives = 2;
            _speed = 4;
            ShootSpeed = 8;
            Score = 0;
            LoadAnimation(_animList);
            LoadSounds(_soundList);
        }
        protected override void LoadAnimation(Dictionary<string, Animation> animList)
        {
            _godModeUp = animList["godModeUp"];
            _godModeDown = animList["godModeDown"];
            _godModeLeft = animList["godModeLeft"];
            _godModeRight = animList["godModeRight"];

            base.LoadAnimation(animList);
        }
        void LoadSounds(Dictionary<string, SoundEffect> soundList)
        {
            _moveSound = soundList["moveSound"];
            _dieSound = soundList["dieSound"];
            _engineSound = soundList["engineSound"];
            _bonusSound = soundList["bonusSound"];
            _lifeSound = soundList["lifeSound"];
            _skillSound = soundList["skillSound"];
        }
        public override void Initialize()
        {
            _sprite.PlayAnimation(_portal);
            base.Initialize();
        }
        void IsCollideWithBonus(GameTime time)
        {
            Bonus bonus = null;
            for (int i = 0; i < Game.Components.Count; i++)
            {
                if (Game.Components[i].GetType() == (typeof(Bonus)))
                {
                    gBaseClass spr = Game.Components[i] as gBaseClass;
                    if (IsCollideWithObject(spr))
                    {
                        bonus = spr as Bonus;
                        ApplyBonus(bonus, bonus.Type, time);
                    }
                }
            }
        }
        void ApplyBonus(Bonus bonus, byte type, GameTime time)
        {
            switch (type)
            {
                case 1:
                    bonus.Dispose();
                    _lifeSound.Play();
                    ++Lives;
                    break;
                case 2:
                    bonus.Dispose();
                    _bonusSound.Play();
                    FreezeAllEnemies(time);
                    _freezedEnemies = true;
                    break;
                case 3:
                    bonus.Dispose();
                    _bonusSound.Play();
                    GodModeOn(time);
                    break;
                case 4:
                    bonus.Dispose();
                    _bonusSound.Play();
                    KillAllEnemies();
                    break;
                case 5:
                    bonus.Dispose();
                    _skillSound.Play();
                    ++Skill;
                    break;
                case 6:
                    bonus.Dispose();
                    _bonusSound.Play();
                    StoneBaseBonus(time);
                    _stoneBase = true;
                    break;
            }
        }
        void KillAllEnemies()
        {
            for (int i = 0; i < Game.Components.Count; i++)
            {
                if (Game.Components[i].GetType() == (typeof(Enemy)))
                {
                    Enemy en = Game.Components[i] as Enemy;
                    if (en._iter >= 305)
                        en.Kill();
                }
            }
        }
        void FreezeAllEnemies(GameTime time)
        {
            _freezeTime = time.TotalGameTime.TotalSeconds;
            for (int i = 0; i < Game.Components.Count; i++)
            {
                if (Game.Components[i].GetType() == (typeof(Enemy)))
                {
                    Enemy en = Game.Components[i] as Enemy;
                    en.Freeze();
                }
            }
        }
        void UnFreezeAllEnemies()
        {
            for (int i = 0; i < Game.Components.Count; i++)
            {
                if (Game.Components[i].GetType() == (typeof(Enemy)))
                {
                    Enemy en = Game.Components[i] as Enemy;
                    en.UnFreeze();
                }
            }
        }
        void StoneBaseBonus(GameTime time)
        {
            _baseWalls = new List<Wall>();
            for (int i = 0; i < Game.Components.Count; i++)
            {
                if (Game.Components[i].GetType() == (typeof(Wall)))
                {
                    Wall bWall = Game.Components[i] as Wall;
                    if (bWall.SprPosition.X == 176 && bWall.SprPosition.Y == 368)
                    {
                        _baseWalls.Add(bWall);
                    }
                    if (bWall.SprPosition.X == 176 && bWall.SprPosition.Y == 384)
                    {
                        _baseWalls.Add(bWall);
                    }
                    if (bWall.SprPosition.X == 176 && bWall.SprPosition.Y == 400)
                    {
                        _baseWalls.Add(bWall);
                    }
                    if (bWall.SprPosition.X == 192 && bWall.SprPosition.Y == 368)
                    {
                        _baseWalls.Add(bWall);
                    }
                    if (bWall.SprPosition.X == 208 && bWall.SprPosition.Y == 368)
                    {
                        _baseWalls.Add(bWall);
                    }
                    if (bWall.SprPosition.X == 224 && bWall.SprPosition.Y == 368)
                    {
                        _baseWalls.Add(bWall);
                    }
                    if (bWall.SprPosition.X == 224 && bWall.SprPosition.Y == 384)
                    {
                        _baseWalls.Add(bWall);
                    }
                    if (bWall.SprPosition.X == 224 && bWall.SprPosition.Y == 400)
                    {
                        _baseWalls.Add(bWall);
                    }
                }
            }
            ChangeWallsIntoStone(time);
        }
        void BrickBase()
        {
            _stoneBaseWalls = new List<Stone>();
            foreach (gBaseClass spr in Game.Components)
            {
                if (spr.GetType() == (typeof(Stone)))
                {
                    Stone sWall = spr as Stone;
                    if (spr.SprPosition.X == 176 && spr.SprPosition.Y == 368)
                    {
                        _stoneBaseWalls.Add(sWall);
                    }
                    if (spr.SprPosition.X == 176 && spr.SprPosition.Y == 384)
                    {
                        _stoneBaseWalls.Add(sWall);
                    }
                    if (spr.SprPosition.X == 176 && spr.SprPosition.Y == 400)
                    {
                        _stoneBaseWalls.Add(sWall);
                    }
                    if (spr.SprPosition.X == 192 && spr.SprPosition.Y == 368)
                    {
                        _stoneBaseWalls.Add(sWall);
                    }
                    if (spr.SprPosition.X == 208 && spr.SprPosition.Y == 368)
                    {
                        _stoneBaseWalls.Add(sWall);
                    }
                    if (spr.SprPosition.X == 224 && spr.SprPosition.Y == 368)
                    {
                        _stoneBaseWalls.Add(sWall);
                    }
                    if (spr.SprPosition.X == 224 && spr.SprPosition.Y == 384)
                    {
                        _stoneBaseWalls.Add(sWall);
                    }
                    if (spr.SprPosition.X == 224 && spr.SprPosition.Y == 400)
                    {
                        _stoneBaseWalls.Add(sWall);
                    }
                }
            }
            ChangeWallsIntoBrick();
        }
        void ChangeWallsIntoStone(GameTime time)
        {
            _stoneBaseTime = time.TotalGameTime.TotalSeconds;
            Texture2D stone = Game.Content.Load<Texture2D>("stone");
            for (int i = 0; i < Game.Components.Count; i++)
            {
                if (Game.Components[i].GetType() == (typeof(Wall)))
                {
                    Wall wall = Game.Components[i] as Wall;
                    Game.Components.Remove(wall);
                    Game.Components.Add(new Stone(Game as BattleCityGame, stone, new Vector2((wall.SprPosition.X) / 16, (wall.SprPosition.Y) / 16)));
                }
            }
        }
        void ChangeWallsIntoBrick()
        {
            Texture2D brick = Game.Content.Load<Texture2D>("wall");
            for (int i = 0; i < Game.Components.Count; i++)
            {
                if (Game.Components[i].GetType() == (typeof(Stone)))
                {
                    Stone wall = Game.Components[i] as Stone;
                    Game.Components.Remove(wall);
                    Game.Components.Add(new Wall(Game as BattleCityGame, brick, new Vector2((wall.SprPosition.X) / 16, (wall.SprPosition.Y) / 16)));
                }
            }
        }
        //Процедура, отвечающая за перемещение игрового объекта
        void GetInput()
        {
            if (IsAlive)
            {
                KeyboardState kbState = Keyboard.GetState();
                if (kbState.IsKeyDown(Keys.Space) && !_isShootNow)
                    Shoot();
                //При нажатии кнопки "Вверх"
                if (kbState.IsKeyDown(Keys.Up) && !_isMoveNow)
                {
                    MoveUp(_speed);
                    _dir = Direction.Up;
                    _isMoveNow = true;
                    if (_isGod)
                        _sprite.PlayAnimation(_godModeUp);
                    else
                        _sprite.PlayAnimation(_moveUpAnimation);
                    _moveSound.Play();
                    while (IsCollideWithWall())
                    {
                        MoveDown((0.5f));
                    }
                }

                //При нажатии кнопки "Вниз"
                //Происходит обычная процедура перемещения
                //объекта с проверкой
                if (kbState.IsKeyDown(Keys.Down) && !_isMoveNow)
                {
                    MoveDown(_speed);
                    _dir = Direction.Down;
                    _isMoveNow = true;
                    if (_isGod)
                        _sprite.PlayAnimation(_godModeDown);
                    else
                        _sprite.PlayAnimation(_moveDownAnimation);
                    _moveSound.Play();
                    while (IsCollideWithWall())
                    {
                        MoveUp((0.5f));
                    }
                }
                //Точно так же обрабатывается
                //нажатие кнопки "Влево"
                if (kbState.IsKeyDown(Keys.Left) && !_isMoveNow)
                {
                    MoveLeft(_speed);
                    _dir = Direction.Left;
                    _isMoveNow = true;
                    if (_isGod)
                        _sprite.PlayAnimation(_godModeLeft);
                    else
                        _sprite.PlayAnimation(_moveLeftAnimation);
                    _moveSound.Play();
                    while (IsCollideWithWall())
                    {
                        MoveRight((0.5f));
                    }
                }
                //Аналогично - перемещение вправо
                if (kbState.IsKeyDown(Keys.Right) && !_isMoveNow)
                {
                    MoveRight(_speed);
                    _dir = Direction.Right;
                    _isMoveNow = true;
                    if (_isGod)
                        _sprite.PlayAnimation(_godModeRight);
                    else
                        _sprite.PlayAnimation(_moveRightAnimation);
                    _moveSound.Play();
                    while (IsCollideWithWall())
                    {
                        MoveLeft((0.5f));
                    }
                }
            }
        }
        void DirectionAnimation()
        {
            if (IsAlive)
            {
                switch (_dir)
                {
                    case Direction.Up:
                        if (_isGod)
                            _sprite.PlayAnimation(_godModeUp);
                        else
                            _sprite.PlayAnimation(_idleUp);
                        break;
                    case Direction.Down:
                        if (_isGod)
                            _sprite.PlayAnimation(_godModeDown);
                        else
                            _sprite.PlayAnimation(_idleDown);
                        break;
                    case Direction.Left:
                        if (_isGod)
                            _sprite.PlayAnimation(_godModeLeft);
                        else
                            _sprite.PlayAnimation(_idleLeft);
                        break;
                    case Direction.Right:
                        if (_isGod)
                            _sprite.PlayAnimation(_godModeRight);
                        else
                            _sprite.PlayAnimation(_idleRight);
                        break;
                }
            }
        }
        void EngineSoundPlay()
        {
            if (!_isMoveNow && _iter % 5 == 0)
            {
                _engineSound.Play(0.6f, 0f, 0f);
            }
        }
        void Destroy(GameTime time)
        {
            if (Lives == 0 && GameOver != null)
            {
                IsAlive = false;
                GameOver(this, new EventArgs());
            }
            --Lives;
            _isDie = true;
            _dieTime = time.TotalGameTime.TotalSeconds;
            _sprite.PlayAnimation(_destroy);
            _dieSound.Play();
        }
        void Reset(GameTime time)
        {
            IsAlive = true;
            SprPosition.X = 128;
            SprPosition.Y = 384;
            GodModeOn(time);
            _isMoveNow = false;
            _isShootNow = false;
            _isMultiShoot = false;
            _isSuper = false;
            _flag = false;
            Skill = 0;
        }
        void GodModeOn(GameTime time)
        {
            _isGod = true;
            _godModeTime = time.TotalGameTime.TotalSeconds;
        }
        void SkillCheck()
        {
            switch (Skill)
            {
                case 1:
                    ShootSpeed = 16;
                    break;
                case 2:
                    _isMultiShoot = true;
                    break;
                case 3:
                    _isSuper = true;
                    break;
                default:
                    break;
            }
        }
        public override void Update(GameTime gameTime)
        {
            _iter++;
            if (_iter <= 150)
            {
                _sprite.PlayAnimation(_portal);
            }
            else
            {
                if (_iter == 151)
                    GodModeOn(gameTime);
                EngineSoundPlay();
                DirectionAnimation();
                IsCollideWithBonus(gameTime);
                SkillCheck();
                GetInput();
                Check();
                _isMoveNow = false;
                if (gameTime.TotalGameTime.TotalSeconds - _godModeTime >= 3 && _isGod)
                {
                    _isGod = false;
                }
                if (gameTime.TotalGameTime.TotalSeconds - _stoneBaseTime >= 20 && _stoneBase)
                {
                    _stoneBase = false;
                    BrickBase();
                }
                if (gameTime.TotalGameTime.TotalSeconds - _freezeTime >= 20 && _freezedEnemies)
                {
                    _freezedEnemies = false;
                    UnFreezeAllEnemies();
                }
                if (!IsAlive && !_flag)
                {
                    Destroy(gameTime);
                    _flag = true;
                }
                if (Lives >= 0 && !_isDie && !IsAlive && Lives <= 50)
                    Reset(gameTime);
                if (gameTime.TotalGameTime.TotalSeconds - _dieTime >= 1 && _isDie)
                    _isDie = false;
            }
            base.Update(gameTime);
        }
    }
}